﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Way.Bus.WMS.Model;
using Way.Bus.Controllers;
using Way.Contract;
using Way.Contract.MVC;
using Way.EAP.DataAccess.Entity;
using Way.Contract.Data.ControllerData;
using Way.Contract.Data;
using Way.Bus.Model;
using Way.EAP.DataAccess.Data;
using System.Data;
using Way.Contract.Center;
using Way.EAP.DataAccess.Regulation;
using Way.Bus.Wms.Controllers.BaseData;

namespace Way.Bus.WMS.Controllers
{
    public class StockOutOrderController : BusinessController
    {
        /// <summary>
        /// 描述：出库单控制器(继承此控制器)
        /// 创建日期:2012-12-21
        /// </summary>
        public StockOutOrderController() : base(new StockOutOrder()) { }

        public StockOutOrderController(IModel model) : base(model) { }

        #region 初始化数据方法

        //是否启用提交
        public override bool IsSubmit
        {
            get
            {
                return true;
            }
        }

        //是否启用审核
        public override bool IsReviewedState
        {
            get
            {
                return false;
            }
        }

        //是否启用回收站(未启用)
        public override bool IsClearAway
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 启用下推
        /// </summary>
        public override bool IsPushDown
        {
            get
            {
                return false;
            }
        }

        //显示在菜单
        protected override string OnControllerName()
        {
            return "出库单管理";
        }

        //菜单中url路径
        protected override string OnGetPath()
        {
            return "Views/WMS/StockOutOrder/StockOutOrder.htm";
        }

        //开发人
        protected override string OnGetAuthor()
        {
            return "";
        }

        //说明
        protected override string OnGetControllerDescription()
        {
            return "出库单管理";
        }

        /// <summary>
        /// 初始化显示字段
        /// </summary>
        /// <param name="data"></param>
        /// <param name="item"></param>
        protected override void OnInitViewChildItem(Way.Contract.Data.ModelData data, Way.Contract.Data.ItemData item)
        {
            base.OnInitViewChildItem(data, item);
            if (item.IsField("IsDisable"))
                item.visible = false;
            if (data.name.EndsWith("Materials"))
            {
                if (item.IsField("Createdby"))
                    item.title = "库管";
                if (item.IsField("Creationdate"))
                    item.title = "作业时间";
                if (item.IsField("DEPOTWBS"))
                {
                    if (item.foreign != null)
                    {
                        item.foreign.rowdisplay.Add("WAREHOUSENAME", "HQName");
                        item.foreign.rowdisplay.Add("SUBNO", "SENBATCHNO");
                        item.foreign.rowdisplay.Add("BATCHNO", "BATCHNO");
                    }
                }
            }
            //关闭多余的叶签
            if (data.name.EndsWith("StockOutNoticeMaterials1"))
            {
                data.visible = false;
            }
            if (data.name.EndsWith("LogData"))
            {
                data.visible = false;
            }
            #region 不要
            //if (data.name.EndsWith("StockOutOrder"))
            //{

            //    switch (item.field.ToLower())
            //    {
            //        case "id":
            //        case "modifiedby":
            //        case "modifieddate":
            //        case "isdisable":
            //        case "isdelete":
            //        case "state":
            //        case "carphone":
            //        case "stocktype":
            //            item.visible = false;
            //            break;
            //        case "code":
            //            item.visible = true;
            //            item.isedit = false;
            //            item.disabled = true;
            //            item.title = "出库单号";
            //            break;
            //        case "sourcecode":
            //            item.visible = true;
            //            item.title = "来源单号";
            //            item.required = true;
            //            break;

            //        case "towhno":
            //            item.title = "出库仓库";
            //            item.required = true;
            //            break;
            //        case "bumen":
            //            item.disabled = true;
            //            break;
            //        case "isreviewed":
            //        case "reviewedby":
            //        case "revieweddate":
            //            item.disabled = true;
            //            item.visible = false;
            //            break;
            //        case "issynchronous":
            //            item.disabled = true;
            //            break;
            //    }
            //}

            //if (data.name.EndsWith("StockOutOrderMaterials"))
            //{
            //    //产品编码带出规格型号
            //    if (item.field == "MATERIALCODE")
            //    {
            //        if (item.foreign != null)
            //        {
            //            item.foreign.rowdisplay.Add("FMODEL", "FMODEL");
            //            item.foreign.rowdisplay.Add("CODE", "MCODE");
            //        }
            //    }
            //    switch (item.field.ToLower())
            //    {
            //        case "submiteddate":
            //        case "submitedby":
            //        case "createdby":
            //        case "creationdate":
            //        case "modifiedby":
            //        case "modifieddate":
            //        case "reviewedby":
            //        case "revieweddate":
            //        case "issubmited":
            //        case "isreviewed":
            //        case "isdisable":
            //        case "isdelete":
            //        case "id":
            //        case "code":
            //        case "morderno":
            //        case "sourceno":
            //        case "num2":
            //        case "num3":
            //        case "ckmxorderno":
            //        case "sourcecode"://源单编码
            //        case "price":
            //        case "parentid":
            //            item.visible = false;
            //            item.disabled = true;
            //            break;
            //        case "fmodel":
            //        case "mcode":
            //            item.disabled = true;
            //            item.visible = true;
            //            break;
            //        case "finishnum":
            //            item.disabled = true;
            //            break;
            //    }
            //}
            //if (data.name.EndsWith("StockOutNoticeMaterials"))
            //{
            //    data.title = "待出库明细";
            //    switch (item.field.ToLower())
            //    {
            //        case "parentid":
            //            item.visible = false;
            //            item.foreign.isfkey = true;
            //            item.foreign.foreignfiled = "SOURCEID";
            //            item.foreign.filedname = item.field;
            //            //item.foreign.displayfield = ("ModelName").ToUpper();显示的名称
            //            item.foreign.objectname = data.name;
            //            item.foreign.foreignobject = "Way.Bus.WMS.Model.StockOutOrder";
            //            item.foreign.tablename = "Acc_WMS_OutOrder";
            //            break;
            //    }
            //}
            #endregion
        }

        protected override void OnForeignIniting(IModel model, InitData data)
        {
            if (model is StockOutOrderMaterials)
            {
                if (this.fdata.filedname == "DEPOTWBS")
                {
                    StockInfoMaterialsController.OnInitForeignStockInfoMaterials((StockOutOrderMaterials)model, data);
                    foreach (ItemData d in data.modeldata.childitem)
                    {
                        if (d.IsField("MCODE") || d.IsField("MNAME") || d.IsField("model"))
                            d.visible = false;
                    }
                }
            }
        }

        protected override ReadTable OnForeignLoad(IModel model, loadItem item)
        {
            ///选择仓库的sql
            if (this.fdata.filedname == "TOWHNO")
            {
                item.rowsql = "select * from (" + item.rowsql + ") a where a.ParentId=0";
            }
            //选择货位
            if (this.fdata.filedname == "DEPOTWBS")
            {
                int orderid = int.Parse(ActionItem["ID"].ToString());
                int wid, mid = 0;
                if (Convert.ToInt32(this.ActionItem["TOWHNO"]) > 0)
                    wid = int.Parse(this.ActionItem["TOWHNO"].ToString());
                else
                    throw new Exception("异常：请先选择仓库！");
                StockOutOrderMaterials mm = EntityHelper.ToEntity(this.fdata.eventrow, typeof(StockOutOrderMaterials)) as StockOutOrderMaterials;
                if (mm != null && mm["MATERIALCODE"] != null && !string.IsNullOrEmpty(mm["MATERIALCODE"].ToString()))
                    mid = int.Parse(mm["MATERIALCODE"].ToString());
                else
                    throw new Exception("异常：请先选择商品！");
                string batchno = "";
                if (mm != null && mm["batchno"] != null)
                    batchno = mm["batchno"].ToString();
                string subno = "";
                if (mm != null && !string.IsNullOrEmpty(mm.SENBATCHNO))
                    subno = mm.SENBATCHNO;
                item.sort = "batchno";
                item.rowsql = StockInfoView.GetStockSQL(orderid, wid, mid, 0, batchno, subno);
            }
            return base.OnForeignLoad(model, item);
        }
        protected override void OnForeignLoaded(IModel model, ReadTable table)
        {
            if (this.fdata.filedname == "DEPOTWBS")
            {
                //table.rows.Columns.Add("ID");
                table.rows.Columns.Add("CODE");
                foreach (DataRow r in table.rows.Rows)
                {
                    r["ID"] = r["DID"];
                    r["CODE"] = r["DCODE"];
                }
            }
            base.OnForeignLoaded(model, table);
        }
        #endregion

        #region 增删改方法
        /// <summary>
        /// 添加默认值
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public StockOutOrder AddDefault(ControllerBase.SaveEvent item)
        {
            StockOutOrder si = item.Item as StockOutOrder;
            EntityList<StockOutNotice> list = new EntityList<StockOutNotice>(this.model.GetDataAction());
            list.GetData(" ID='" + si.SourceID + "'");
            bool bl = true;//用于判断入库单明细中的货物编码是否在预收单明细中存在的标志位
            if (list.Count > 0)
            {
                list[0].Materials.DataAction = this.model.GetDataAction();
                list[0].Materials.GetData();
                si.SourceController = "Way.Bus.WMS.ST.Controllers.OutOrder.ST_OutNoticeController";
                si.SourceID = list[0].ID;
                for (int j = 0; j < si.Materials.Count; j++)
                {
                    for (int i = 0; i < list[0].Materials.Count; i++)
                    {
                        //预收单的货物明细与入库单货物明细改为只按照Mcode进行比较 --1203 
                        //if (si.Materials[j].MCODE == list[0].Materials[i].MCODE && si.Materials[j].BATCHNO == list[0].Materials[i].BATCHNO ) 
                        if (si.Materials[j].MCODE == list[0].Materials[i].MCODE)
                        {
                            si.Materials[j].SourceRowID = list[0].Materials[i].ID;
                            si.Materials[j].SourceID = list[0].Materials[i].PARENTID;
                            si.Materials[j].SourceTable = list[0].Materials[i].ToString();
                            bl = false;
                        }
                    }
                    if (bl)
                    {
                        Materials a = si.Materials[j].GetForeignObject<Materials>(this.model.GetDataAction());
                        throw new Exception(" 商品名称:" + a.FNAME + "  商品编码：" + a.Code + " 出库单明细中的货物编码在发货通知中不存在！");
                    }
                }


            }
            else
            {
                //如果没有对应的预收单，不做任何加工，直接返回入库单信息
            }
            return si;
        }
        protected override void OnAdding(ControllerBase.SaveEvent item)
        {
            StockOutOrder order = (StockOutOrder)item.Item;
            //AddDefault(item);
            order.STOCKTYPE = this.StockType();
            //合并相同数据行
            MergerOrderMaterials(order);

            IDataAction action = this.model.GetDataAction();
            ValidateMain(order, action);
            CheckPDOrder(order, action);
            base.OnAdding(item);
        }


        /// <summary>
        /// 编辑方法
        /// </summary>
        /// <param name="item"></param>
        protected override void OnEditing(ControllerBase.SaveEvent item)
        {
            base.OnEditing(item);
            //AddDefault(item);
            StockOutOrder order = (StockOutOrder)item.Item;
            order.STOCKTYPE = this.StockType();
            //合并相同数据行
            IDataAction action = this.model.GetDataAction();
            MergerOrderMaterials(order);
            ValidateMain(order, action);
            CheckPDOrder(order, action);
        }


        protected override void OnRemoveing(ControllerBase.SaveEvent item)
        {
            base.OnRemoveing(item);
        }

        protected override void OnGetWhereing(IModel m, List<SQLWhere> where, loadItem item)
        {
            string extCondition = item.where;//存放额外条件
            item.where = "";//将where属性置空，以免影响其他用到where属性的程序
            EntityBase ieb = (EntityBase)item.selectTag;
            if (ieb == null)
            {
                ieb = (EntityBase)m;
            }
            if (ieb != null)
            {
                ieb.IsAddProperty = false;
                if (((IEntityBase)ieb).IsHaveProperty("StockType"))
                {
                    SQLWhere w = new SQLWhere();
                    w.ColumnName = "StockType";
                    w.Value = this.StockType().ToString();
                    if (w.Value != "-1")
                        where.Add(w);
                }

            }
            base.OnGetWhereing(m, where, item);
            if ((item.selectTag != null && item.selectTag is StockOutOrderMaterials) || extCondition == "NotAddRoleData") return;
            WmsRoleDataController.SearchManage(this, where, item);
        }

        protected virtual int StockType()
        {
            return -1;
        }

        #endregion

        #region 业务处理自定义方法


        protected virtual BusinessController GetSourceController()
        {
            return new StockOutNoticeController();
        }
        /// <summary>
        /// 添加时设置源控制器属性（主表：SourceController、SourceID、SourceCode）、（子表：SourceRowID、SourceTable）
        /// </summary>
        /// <param name="item"></param>
        public void SetAddingSourcePorp(ControllerBase.SaveEvent item)
        {
            StockOutOrder ord = item.Item as StockOutOrder;
            StockOutNoticeMaterials sm = new StockOutNoticeMaterials();
            if (ord.SourceCode != null && ord.SourceID <= 0 && string.IsNullOrEmpty(ord.SourceController))
            {
                EntityList<StockOutNotice> notice = new EntityList<StockOutNotice>(this.model.GetDataAction());
                notice.GetData("code='" + ord.SourceCode + "'");
                ///如果目标单据的sourceId =0 代表没有使用下推方法，则赋值SourceID和SourceController
                if (notice.Count > 0)
                {
                    ord.SourceID = notice[0].ID;
                    ord.SourceController = GetSourceController().GetType().FullName;
                    var a = notice[0].Materials;
                    a.DataAction = this.model.GetDataAction();
                    a.GetData();
                    for (int i = 0; i < a.Count; i++)
                    {
                        for (int j = 0; j < ord.Materials.Count; j++)
                        {
                            if (!string.IsNullOrEmpty(a[i].BATCHNO.Trim()))
                            {
                                if (a[i].MATERIALCODE == ord.Materials[j].MATERIALCODE && a[i].BATCHNO.Trim() == ord.Materials[j].BATCHNO.Trim())
                                {
                                    ord.Materials[j].SourceRowID = a[i].ID;
                                    ord.Materials[j].SourceTable = sm.ToString();
                                }
                            }
                            else
                            {
                                if (a[i].MATERIALCODE == ord.Materials[j].MATERIALCODE && ord.Materials[j].SourceRowID == 0)
                                {
                                    ord.Materials[j].SourceRowID = a[i].ID;
                                    ord.Materials[j].SourceTable = sm.ToString();
                                }
                            }
                        }
                    }

                }
            }
        }
        /// <summary>
        /// 验证主单
        /// </summary>
        protected virtual void ValidateMain(StockOutOrder order, IDataAction action)
        {
            if (order != null)
            {
                int stockid = order.TOWHNO;
                if (stockid <= 0)
                    throw new Exception("异常：仓库未选择发货仓库，请先选择仓库！");
                ValidateWarehouse(order);
                int orderid = order.ID;
                IHierarchicalEntityView view = order.StayMaterials;
                string sb = view.ChildEntity.ToString();
                foreach (StockOutOrderMaterials m in order.Materials)
                {
                    m.SourceTable = sb; ;
                    ValidateDetail(orderid, stockid, m, order, action);
                }
            }
        }
        /// <summary>
        /// 验证仓库的方法（是否有权限选择出此仓库和不能为空）
        /// </summary>
        /// <param name="item"></param>
        protected virtual void ValidateWarehouse(StockOutOrder item)
        {
            IDataAction action = this.model.GetDataAction();
            //WareHouse wh = item.GetForeignObject<WareHouse>(action);
            //wh.ChildOffice.DataAction = action;
            //wh.ChildOffice.GetData();
            //if (wh.ISOFFER && wh.ChildOffice.Count > 0)
            //{
            //    bool iswork = wh.ChildOffice.Exists(delegate(OWorker ow) { return ow.ID.ToString() == this.user.ID; });
            //    if (!iswork)
            //        throw new Exception("异常：登陆人+" + this.user.name + ",不是" + wh.WAREHOUSENAME + "的管理员，不能操作仓库业务！");
            //}
        }


        /// <summary>
        /// 验证单行明细数量
        /// </summary>
        /// <param name="item"></param>
        protected virtual void ValidateDetail(int orderid, int stockid, StockOutOrderMaterials item, StockOutOrder order, IDataAction action)
        {
            if (item.NUM <= 0)
                throw new Exception("序号：" + item.RowIndex + "行异常，发放数量不能小于等于0！");
            //有源数量效验
            HaveSourceValidateNum(item);
            ValidateDepotwbs(order, item, action);
            ValidateStockNum(item, orderid, stockid);
            ValidateBatchNo(item);

            item.Createdby = this.user.ID;
            item.Creationdate = DateTime.Now;
        }

        /// <summary>
        /// 有源单发放数量验证
        /// </summary>
        /// <param name="item"></param>
        protected virtual void HaveSourceValidateNum(StockOutOrderMaterials item)
        {
            if (item.SourceRowID > 0)
            {
                double SourceNum = item.GetNum(item.SourceTable, item.SourceRowID);//源单要求发放数量
                double num = item.GetSourceNum(item.SourceTable, item.SourceRowID, item.MATERIALCODE, item.PARENTID);//已在其他发货单录入数量
                if (num >= SourceNum)
                    throw new Exception("序号：" + item.RowIndex + "行异常，已在其他单发放完成，不能再次发出！");
                double newnum = 0;
                EntityList<StockOutOrderMaterials> list = ((IEntityBase)item).ParentList as EntityList<StockOutOrderMaterials>;
                if (list != null)
                {
                    var result = from o in list group o by new { o.SourceRowID, o.MATERIALCODE } into g select new { g.Key, Totle = g.Sum(p => p.NUM), Items = g.ToList<StockOutOrderMaterials>() };
                    foreach (var r in result)
                    {
                        if (r.Key.SourceRowID == item.SourceRowID)
                        {
                            newnum = r.Totle;
                            if (newnum > SourceNum)
                                throw new Exception("异常：当前明细行中的" + item.GetAppendPropertyValue("MATERIALCODE").ToString() + "总发放数量为" + r.Totle + ",超出要求发放数量" + SourceNum + "!");
                            if ((newnum + num) > SourceNum)
                                throw new Exception("异常：当前明细行中的" + item.GetAppendPropertyValue("MATERIALCODE").ToString() + "总发放数量为" + r.Totle + ",其他单据中已发放" + num + ",超出要求发放数量" + SourceNum + "!");
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 库存数量与发放数量验证
        /// </summary>
        /// <param name="orderid">单据ID</param>
        /// <param name="stockid">仓库ID</param>
        protected virtual void ValidateStockNum(StockOutOrderMaterials item, int orderid, int stockid)
        {
            if (string.IsNullOrEmpty(item.DEPOTWBS))
                throw new Exception("异常：序号" + item.RowIndex + "货位不能为空！");
            int wid = stockid;
            int mid = int.Parse(item.MATERIALCODE);
            int did = int.Parse(item.DEPOTWBS);
            string sql = StockInfoView.GetStockSQL(orderid, wid, mid, did, item.BATCHNO, item.SENBATCHNO);
            IDataAction action = this.model.GetDataAction();
            DataTable table = action.GetDataTable(sql);
            if (table.Rows.Count > 0)
            {
                double count = 0;
                if (table.Rows[0]["kynum"] != null && !string.IsNullOrEmpty(table.Rows[0]["kynum"].ToString()))
                    count = Convert.ToDouble(table.Rows[0]["kynum"]);
                if (item.NUM > count)
                    throw new Exception("异常：序号" + item.RowIndex + "行出库数量" + item.NUM + "大于可用库存数量" + count + "不能出库！");

            }
            else
                throw new Exception("异常：序号" + item.RowIndex + "行未找到可用库存，不能出库！");
        }
        /// <summary>
        /// 验证批次
        /// </summary>
        /// <param name="item"></param>
        protected virtual void ValidateBatchNo(StockOutOrderMaterials item)
        {
            Materials a = item.GetForeignObject<Materials>(this.model.GetDataAction());
            if (a.BATCH == true && item.BATCHNO == "")
            {
                throw new Exception("异常：" + a.FNAME + ",编码" + a.Code + "为批次管理产品，批次号不能为空！");
            }
        }
        /// <summary>
        /// 验证货位
        /// </summary>
        /// <param name="item"></param>
        protected virtual void ValidateDepotwbs(StockOutOrder order, StockOutOrderMaterials item, IDataAction action)
        {
            int hw = 0;
            if (!string.IsNullOrEmpty(item.DEPOTWBS) && !int.TryParse(item.DEPOTWBS, out hw))
            {
                item.DEPOTWBS = WareHouse.GetDepotwesID(order.TOWHNO, item.DEPOTWBS, action).ToString();
            }
        }
        /// <summary>
        /// 验证是否盘点中
        /// </summary>
        /// <param name="action"></param>
        public virtual void CheckPDOrder(StockOutOrder order, IDataAction action)
        {
            EntityList<CheckOrder> dfList = new EntityList<CheckOrder>(action);
            dfList.GetData("issubmited=1 and isreviewed=0 and checkordertype='1'");
            foreach (CheckOrder item in dfList)
            {
                WareHouse wh = item.GetForeignObject<WareHouse>(action);
                if (wh.WHTYPE == 0)
                {
                    if (wh.ID.Equals(order.TOWHNO))
                        throw new Exception("盘点单：" + item.Code + " 为静态盘点,盘点位置为" + wh.WAREHOUSENAME + "开始盘点中，请结束后执行出库操作！");
                }
                else
                {
                    foreach (StockOutOrderMaterials iom in order.Materials)
                    {
                        if (iom.HQName == wh.WAREHOUSENAME)
                            throw new Exception("盘点单：" + item.Code + " 为静态盘点,盘点位置为" + wh.WAREHOUSENAME + "开始盘点中，请结束后执行出库操作！");
                    }
                }

            }
        }

        /// <summary>
        /// 合并同行(出库产品明细行)
        /// </summary>
        /// <param name="item"></param>
        public virtual void MergerOrderMaterials(StockOutOrder order)
        {
            if (order.Materials.Count == 0) return;
            List<StockOutOrderMaterials> items = new List<StockOutOrderMaterials>();
            var result = from o in order.Materials group o by new { o.SourceRowID, o.MATERIALCODE, o.BATCHNO, o.SENBATCHNO, o.DEPOTWBS } into g select new { g.Key, Totle = g.Sum(p => p.NUM), Items = g.ToList<StockOutOrderMaterials>() };
            foreach (var group in result)
            {
                StockOutOrderMaterials m = group.Items.Find(delegate(StockOutOrderMaterials mm) { return ((IEntityBase)mm).StateBase == EntityState.Select; });
                if (m == null)
                {
                    m = group.Items[0];
                    m.NUM = group.Totle;
                    if (m.SourceRowID > 0)
                    {
                        EntityList<StockOutOrderMaterials> list = new EntityList<StockOutOrderMaterials>(this.model.GetDataAction());
                        list.GetData("SourceRowID=" + m.SourceRowID + "and ParentID=" + order.ID + " and BATCHNO='" + m.BATCHNO + "' and SENBATCHNO='" + m.SENBATCHNO + "' and DEPOTWBS='" + m.DEPOTWBS + "'");
                        if (list.Count > 0)
                        {
                            StockOutOrderMaterials nm = list[0];
                            foreach (string s in ((IEntityBase)nm).GetPropertys())
                                nm[s] = m[s];
                            nm["NUM"] = list[0].NUM + m.NUM;
                            nm.OutInSequence.AddRange(m.OutInSequence);
                            m = nm;
                        }
                        items.Add(m);
                    }
                }
                else
                {
                    m.NUM = group.Totle;
                    items.Add(m);
                }
                if (m.NUM <= 0)
                {
                    throw new Exception("明细行数量错误");
                }
            }

            order.Materials.Clear(false);
            order.Materials.AddRange(items);
        }

        /// <summary>
        /// 验证出库填写的数据的正确性
        /// </summary>
        /// <param name="sm">验证产品出库明细的数据</param>
        /// <param name="son"></param>
        private void ValidateInfo(StockOutOrderMaterials sm, StockOutNotice son)
        {
            //判断出库明细数量不能小于0
            if (sm.NUM < 0)
            {
                throw new Exception("请输入正确的出库数量");
            }
            Materials m = sm.GetForeignObject<Materials>(this.model.GetDataAction());
            //判断产品是否允许负库存，也就是出库数量大于出库数量，如果允许则不判断库存是否满足条件
            if (m.NUMSTATE == false)
            {
                ///验证出库数量是否大于库存数量
                if (sm.NUM > GetMaterialNumByCode(m.Code))
                {
                    throw new Exception("出库数量不能大于库存数量");
                }
            }
            ///验证实际出库数量是否大于单据出库数量
            if (sm.NUM > son.Materials[0].NUM)
            {
                throw new Exception("实际出库数量大于通知据数量");
            }
        }

        /// <summary>
        /// 根据产品编码查询库存，作为出库不允许负数时候的判断条件
        /// </summary>
        /// <param name="materialCode">参数产品编码</param>
        /// <returns>返回产品数量</returns>
        private double GetMaterialNumByCode(string materialCode)
        {
            return (double)WMShelp.GetMaterialNumByCode(materialCode, this.model);
        }

        #endregion

        #region 添加按钮方法（出库流程方法）
        protected override ActionCommand[] OnInitCommand(ActionCommand[] commands)
        {
            commands = base.OnInitCommand(commands);
            foreach (ActionCommand ac in commands)
            {
                if (ac.command == "UnSubmitData")
                {
                    ac.visible = false;
                }
            }
            return commands;
        }
        /// <summary>
        /// 重写提交
        /// </summary>
        /// <param name="info"></param>
        protected override void OnSubmitData(BasicInfo info)
        {
            if (!info.IsSubmited)
            {
                StockOutOrder order = info as StockOutOrder;
                if (order.Materials.Count == 0)
                {
                    order.Materials.DataAction = this.model.GetDataAction();
                    order.Materials.GetData();
                }

                if (order.Materials.Count > 0)
                {
                    foreach (StockOutOrderMaterials om in order.Materials)
                        setHWStatus(om.DEPOTWBS, true);
                    base.OnSubmitData(order);

                }
                else
                {
                    throw new Exception("异常：单据无明细数据，不能提交！");
                }
            }
            else
            {
                throw new Exception("异常：单据已提交，不能再次提交！");
            }
            //判断是否启用审核，如果没启用则直接出库
            if (!this.IsReviewedState)
            {
                OutWarehouse(info);
            }
        }
        //更新货位状态：货位是否已满（可用）
        public void setHWStatus(string depotwbs, bool bl)
        {
            WareHouse wh = new WareHouse();
            string sql = "update " + wh.ToString() + " set STATUS='" + (bl ? 0 : 1).ToString() + "' where id = '" + depotwbs + "'";
            this.model.GetDataAction().Execute(sql);

        }

        /// <summary>
        /// 审核按钮
        /// </summary>
        /// <param name="info"></param>
        protected override void OnReviewedData(BasicInfo info)
        {
            if (!info.IsReviewed)
            {
                OutWarehouse(info);
                base.OnReviewedData(info);
            }
            else
            {
                throw new Exception("异常：单据已审核，不能再次审核！");
            }

        }

        ///// <summary>
        ///// 验证入库权限是否可以通过
        ///// </summary>
        ///// <param name="stockinorder"></param>
        //public virtual void ValidateWareHouse(StockOutOrder stockinorder)
        //{
        //    EntityList<OWorker> ow = new EntityList<OWorker>(this.model.GetDataAction());
        //    ow.GetData();
        //    if (ow.Count > 0)
        //    {
        //        int res = 0;
        //        ow.GetData("workName='" + this.user.ID + "'");
        //        if (ow.Count > 0)
        //        {
        //            for (int i = 0; i < ow.Count; i++)
        //            {
        //                EntityList<WareHouse> wh = new EntityList<WareHouse>(this.model.GetDataAction());
        //                wh.GetData("(type=" + ow[i].WHID + " or id=" + ow[i].WHID + ") and ISOFFER=1");
        //                for (int j = 0; j < wh.Count; j++)
        //                {
        //                    if (Convert.ToInt32(stockinorder.TOWHNO) == wh[j].ID)
        //                    {
        //                        res = 1;

        //                    }

        //                }

        //            }
        //            if (res == 0)
        //            {
        //                throw new Exception("异常：没有入库到此仓库的权限");
        //            }
        //        }
        //        else
        //        {
        //            throw new Exception("异常：没有入库到此仓库的权限");
        //        }
        //    }
        //}

        public virtual void OutWarehouse(BasicInfo info)
        {
            IDataAction action = this.model.GetDataAction();
            try
            {
                action.StartTransation();
                StockInfoMaterialsController smc = new StockInfoMaterialsController();
                StockOutOrder order = info as StockOutOrder;
                if (order != null)
                {
                    order.Materials.DataAction = action;
                    order.Materials.GetData();
                    var result = from o in order.Materials group o by new { o.MATERIALCODE, o.BATCHNO, o.DEPOTWBS, o.PORTNAME, o.SENBATCHNO } into g select new { g.Key, Totle = g.Sum(p => p.NUM), Items = g.ToList<StockOutOrderMaterials>() };
                    List<StockOutOrderMaterials> list = new List<StockOutOrderMaterials>();
                    foreach (var ggg in result)
                        list.Add(ggg.Items[0]);
                    if (list.Count > 0)
                    {
                        StockInfoMaterials infoList = new StockInfoMaterials();
                        EntityList<Materials> ms = new EntityList<Materials>(action);
                        InfoInSequence iis = null;
                        for (int i = 0; i < list.Count; i++)
                        {
                            ms.GetData("id='" + list[i].MATERIALCODE + "'");
                            if (ms.Count > 0)
                            {
                                switch (ms[0].STATUS)
                                {
                                    case "2": throw new Exception("产品名称：" + ms[0].FNAME + "  产品编码：" + ms[0].Code + "  状态为冻出，不可进行出库操作");
                                    case "3": throw new Exception("产品名称：" + ms[0].FNAME + "  产品编码：" + ms[0].Code + "  状态为不可用，不可进行出入库操作");
                                }
                                infoList.Code = ms[0].ID.ToString();
                                if (order.TOWHNO == 0)
                                {
                                    throw new Exception("请填写出库仓库");
                                }
                                else
                                {
                                    infoList.WAREHOUSEID = order.TOWHNO;
                                }

                                if (list[i].DEPOTWBS == "")
                                {
                                    list[i].DEPOTWBS = order.TOWHNO.ToString();
                                }
                                else
                                {

                                    string depotwbsCode = infoList.GetAppendPropertyKey("DEPOTWBS");
                                    string depotwbsCode1 = list[i].GetAppendPropertyKey("DEPOTWBS");
                                    infoList.DEPOTWBS = list[i].DEPOTWBS;
                                    infoList[depotwbsCode] = list[i][depotwbsCode1];
                                }
                                if (list[i].PORTNAME != "")
                                {
                                    string portNo = infoList.GetAppendPropertyKey("PORTCODE");
                                    string portNo1 = list[i].GetAppendPropertyKey("PORTNAME");
                                    infoList.PORTCODE = list[i].PORTNAME;
                                    infoList[portNo] = list[i][portNo1];
                                }

                                if (ms[0].BATCH == false)
                                {
                                    list[i].BATCHNO = "";

                                }
                                else
                                {
                                    infoList.BATCHNO = list[i].BATCHNO;
                                    if (list[i].BATCHNO == "")
                                    {
                                        throw new Exception("产品名称：" + ms[0].FNAME + "  产品编码：" + ms[0].Code + "必须允许批次管理，请输入录入批次");
                                    }
                                }
                                infoList.SENBATCHNO = list[i].SENBATCHNO == "" ? "" : list[i].SENBATCHNO;
                                infoList.NUM = Convert.ToDouble(list[i].NUM);
                                infoList.LASTINTIME = DateTime.Now;
                                infoList.Remark = "最后操作：" + this.OnControllerName();
                                if (this.OnControllerName() == "其他出库" || this.OnControllerName() == "生产出库")
                                {
                                    infoList.STAY5 = "qt";
                                }
                                ///更改库存方法
                                ///将出库单件码添加到出库对象中
                                if (list[i].OutInSequence.Count <= 0)
                                {
                                    infoList.StockSequence.Clear();
                                    list[i].OutInSequence.DataAction = action;
                                    list[i].OutInSequence.GetData();
                                    for (int j = 0; j < list[i].OutInSequence.Count; j++)
                                    {
                                        iis = new InfoInSequence();
                                        iis.SEQUENCECODE = list[i].OutInSequence[j].SEQUENCECODE;
                                        infoList.StockSequence.Add(iis);
                                    }
                                }
                                infoList.LASTOUTTIME = DateTime.Now;
                                smc.putin(infoList, "出库", action);
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("异常：单据无明细数据不能出库！");
                    }
                }
                else if (order.IsReviewed == true && order.IsSubmited == true)
                {
                    throw new Exception("异常：已经完成审核！");
                }
                else
                {
                    throw new Exception("异常：单据未提交不能执行审核操作！");
                }

                action.Commit();
            }
            catch (Exception err)
            {
                throw err;
            }
            finally
            {
                action.EndTransation();
            }
        }

        #endregion


        #region 下推转换
        /// <summary>
        /// 单据转换
        /// </summary>
        /// <param name="ca"></param>
        /// <param name="actionItem"></param>
        /// <returns></returns>
        protected override EntityBase OnConvertItem(ControllerAssociate ca, EntityBase actionItem)
        {
            //下推前判断
            WMShelp.IsPush(this);
            StockOutOrder cd = actionItem as StockOutOrder;
            cd.Materials.DataAction = this.model.GetDataAction();
            cd.Materials.GetData();//获取子集的数据
            EntityBase eb = base.OnConvertItem(ca, actionItem);
            //eb = PushInOrder(eb, cd);
            return eb;
        }

        /// <summary>
        /// 出库下推判断
        /// </summary>
        /// <param name="eb"></param>
        /// <param name="cd"></param>
        /// <returns></returns>
        protected virtual EntityBase PushInOrder(EntityBase eb, StockOutOrder cd)
        {
            if (eb is StockOutOrder)
            {
                StockOutOrder ebin = eb as StockOutOrder;
                ebin.SourceCode = cd.SourceCode;
                //ebin.STATE = 1;
                //ebin.STOCKTYPE = 3;
                ebin.IsSubmited = false;
                ebin.IsReviewed = false;
                ebin.SourceID = cd.ID;
                ebin.SourceCode = cd.Code;
                ebin.SourceController = this.ToString();
                ebin.Code = "";
                ebin.Submitedby = "";
                ebin.Submiteddate = DateTime.MinValue;
                ebin.Reviewedby = "";
                ebin.Revieweddate = DateTime.MinValue;
                ebin.Modifiedby = "";
                ebin.Modifieddate = DateTime.MinValue;
                ebin.StayMaterials.GetData();
                ebin.StayMaterials.RemoveAll(delegate(StockOutNoticeMaterials sonm)
                {
                    return sonm.STAYNUM == 0;
                });
                if (ebin.StayMaterials.Count <= 0)
                    throw new Exception("异常：已全部发货完成，不能再次下推！");
            }
            return eb;
        }


        /// <summary>
        /// 单据转换
        /// </summary>
        /// <returns></returns>
        protected override ControllerAssociate[] DownAssociate()
        {
            List<ControllerAssociate> list = new List<ControllerAssociate>();
            //入库单下推其他出库单
            OutOhtherOrder(list);
            return list.ToArray();
        }
        /// <summary>
        /// 应用类中重写此方法
        /// </summary>
        /// <returns></returns>
        protected virtual StockInOrderController GetDownOrder()
        {
            return new StockInOrderController();
        }
        /// <summary>
        /// 入库单-出库单(下推关联)
        /// </summary>
        /// <param name="list"></param>
        private void OutOhtherOrder(List<ControllerAssociate> list)
        {
            //控制器转换器(入库单-出库单)
            // ControllerAssociate bl = new ControllerAssociate(this, new StockElseInOrderController());
            ControllerAssociate bl = new ControllerAssociate(this, GetDownOrder());

            //单据属性映射
            PropertyMap mapORDERID = new PropertyMap();
            ///单号ID --来源单号
            mapORDERID.TargerProperty = "SourceCode";
            mapORDERID.SourceProperty = "Code";
            bl.Convert.AddPropertyMap(mapORDERID);


            //实体类型转换器（入库单-出库单）
            ConvertAssociate NoticeMaterialsToOrderMaterials = new ConvertAssociate();
            NoticeMaterialsToOrderMaterials.SourceType = typeof(StockOutOrderMaterials);//下推来源单据子集
            NoticeMaterialsToOrderMaterials.TargerType = typeof(StockInOrderMaterials);//下推目标单据子集
            YS(NoticeMaterialsToOrderMaterials);
            bl.AddConvert(NoticeMaterialsToOrderMaterials);
            list.Add(bl);
        }

        /// <summary>
        /// 映射
        /// </summary>
        /// <param name="c"></param>
        public void YS(ConvertAssociate c)
        {
            PropertyMap mapMATERIALSID = new PropertyMap();//ID
            mapMATERIALSID.SourceProperty = "CODE";
            mapMATERIALSID.TargerProperty = "SourceCode";
            c.AddPropertyMap(mapMATERIALSID);

            PropertyMap map11 = new PropertyMap();//ID
            map11.SourceProperty = "p.ID";
            map11.TargerProperty = "SourceID";
            PropertyMap map12 = new PropertyMap();//ID
            map12.TargerProperty = "SourceController";
            map12.IsValue = true;
            map12.Value = this.ToString();

            PropertyMap map13 = new PropertyMap();//ID
            map13.SourceProperty = "ID";
            map13.TargerProperty = "SourceRowID";

            PropertyMap map14 = new PropertyMap();//ID
            map14.SourceProperty = "p.Code";
            map14.TargerProperty = "SourceCode";

            PropertyMap map15 = new PropertyMap();//ID
            map15.TargerProperty = "SourceName";
            map15.IsValue = true;
            map15.Value = ((IController)this).ControllerName();

            PropertyMap map16 = new PropertyMap();//ID
            map16.TargerProperty = "SourceTable";
            map16.IsValue = true;
            map16.Value = new StockOutOrderMaterials().ToString();

            c.AddPropertyMap(map11);
            c.AddPropertyMap(map12);
            c.AddPropertyMap(map13);
            c.AddPropertyMap(map14);
            c.AddPropertyMap(map15);
            c.AddPropertyMap(map16);
        }
        #endregion

        //[ActionCommand(name = "打印出库产品条码", title = "打印出库产品条码", index = 6, icon = "icon-ok", onclick = "PrintCode", isselectrow = true)]
        public void Prit()
        {
            //生成界面方法按钮用于权限控制，本方法无代码
        }

        [WhereParameter]
        public string orderid { get; set; }
        public string GetCode()
        {
            string id = "";
            StockOutOrder m = new StockOutOrder();// this.ActionItem as StockInOrder;
            EntityList<StockOutOrder> sio = new EntityList<StockOutOrder>(this.model.GetDataAction());
            sio.GetData("ID='" + orderid + "'");
            m = sio[0];
            m.Materials.GetData();
            for (int i = 0; i < m.Materials.Count; i++)
            {
                if (id == "")
                    id = m.Materials[i].MCODE + "|" + m.Materials[i].MATERIALCODE;
                else
                    id += ";" + m.Materials[i].MCODE + "|" + m.Materials[i].MATERIALCODE;
            }
            return id;
        }
        #region 手持设备方法

        [WhereParameter]
        public string code { get; set; }
        [WhereParameter]
        public int page { get; set; }

        public ReadTable GetMainTable()
        {
            loadItem item = new loadItem();
            item.columns = new string[] { "ID", "CODE", "SourceCode", "TOWHNO", "CLIENTNO" };
            item.page = page.ToString();
            List<SQLWhere> list = new List<SQLWhere>();
            if (!string.IsNullOrEmpty(code))
            {
                SQLWhere w = new SQLWhere();
                w.StartFH = "(";
                w.ColumnName = "Code";
                w.Symbol = "like";
                w.Value = "%" + code + "%";
                list.Add(w);
                SQLWhere w1 = new SQLWhere();
                w1.Relation = "or";
                w1.ColumnName = "SourceCode";
                w1.Symbol = "like";
                w1.Value = "%" + code + "%";
                w1.EndFH = ")";
                list.Add(w1);
            }
            SQLWhere w2 = new SQLWhere();
            w2.ColumnName = "IsSubmited";
            w2.Value = "1";
            list.Add(w2);
            SQLWhere w3 = new SQLWhere();
            w3.ColumnName = "STATE";
            w3.Symbol = "<";
            w3.Value = "2";
            list.Add(w3);
            item.whereList = list.ToArray();
            return this.SearchData(item);
        }
        public ReadTable GetNoticeItems()
        {
            IEntityBase order = this.model as IEntityBase;
            if (order != null)
            {
                foreach (ItemData d in this.Idata.modeldata.childitem)
                {
                    if (d.IsField("SourceCode"))
                    {
                        this.fdata = d.foreign;
                        break;
                    }
                }
                if (this.fdata != null)
                {
                    loadItem item = new loadItem();
                    item.page = page.ToString();
                    List<SQLWhere> list = new List<SQLWhere>();
                    SQLWhere w = new SQLWhere();
                    w.ColumnName = "PARENTID";
                    w.Value = this.code;
                    list.Add(w);
                    item.whereList = list.ToArray();
                    return this.OnForeignLoad(this.model, item);
                }
            }
            return null;
        }
        #endregion

    }
}
